/* OP_CCALL.C
 * Copyright (c) 2007 MissingNODE 
 * Based on GPL OpenQM Code
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * 
 * 
 * START-HISTORY:
 * Oct-10-2007 Initial Revision
 * END-HISTORY
 *
 * START-DESCRIPTION:
 *
 * Copyright (c) 2004 EasyCo LLC, All Rights Reserved
 *
 * op_ccall          CCALL str1,str2
 *
 * Sub-pcode description
 *
 * 'str1' contains p-code that is interpreted here
 *
 *   Opcode - x01 - bin2 len - Library Name - Load librarybinary
 *            x02 - bin 4 lib handle - binary 2 len - Function Name - Get function address
 *            x03 - bin4 - push absolute value on stack
 *            x04 - bin4 str2 offset - push address relative in str2 on stack
 *            x10 - bin2 - sub stack
 *            x11 - bin 4 fn addr - call function
 *            x12 - bin4 str2 offset - pop 32-bit result to relative location in str2
 *            x13 - bin4 str2 offset - pop 64-bit result to relative location in str2
 *
 *            --- others as needed
 *
 * END-DESCRIPTION
 *
 * START-CODE
 */

#include <tm.h>

#include <stdarg.h>
#include <setjmp.h>
#include <time.h>


   #include <dlfcn.h>

/* ======================================================================
   op_ccall(str1,str2)  -  ccall(...,...) function                                                */


private void ccall_c(unsigned char * s1, void * s2)
{
  char * p;
  unsigned char ch;
  unsigned long Val;
  unsigned long Stk[50];
  int StkCnt;
  u_int64 res64;
  void * v;

  u_int64 (* Fn0)();

  StkCnt = 0;

  while(1)
   {
    ch = *s1;
    s1++;
    switch(ch)
     {
      case 1 :                /* dlload / LoadLibrary */
         p = s1;
         s1 += strlen(p) + 1;
         res64 = (unsigned long)dlopen(p, RTLD_NOW|RTLD_GLOBAL);
         break;

      case 2 :                /* dlsym / GetProcAddr */
         p = s1;
         s1 += strlen(p) + 1;
         v = *(void **)s1;
         s1 += sizeof(void *);
         res64 = (unsigned long)dlsym(v,p);
         break;

      case 3 :                /* Push value */
         Stk[StkCnt++] = *(unsigned long *)s1;
         s1 += sizeof(unsigned long *);
         break;

      case 4 :                /* Push mem offset */
         Stk[StkCnt++] = *(unsigned long *)s1 + (unsigned long)s2;
         s1 += sizeof(unsigned long *);
         break;

      case 5 :                /* Inc stack */
         break;

      case 6 :                /* call function */
         Fn0 = *(void **)s1;
         s1 += sizeof(void *);
         switch ( StkCnt )
          {
           case 0 :
             res64 = (*Fn0)();
             break;
           case 1 :
             res64 = (*Fn0)(Stk[0]);
             break;
           case 2 :
             res64 = (*Fn0)(Stk[0],Stk[1]);
             break;
           case 3 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2]);
             break;
           case 4 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3]);
             break;
           case 5 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4]);
             break;
           case 6 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5]);
             break;
           case 7 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6]);
             break;
           case 8 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7]);
             break;
           case 9 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8]);
             break;
           case 10 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9]);
             break;
           case 11 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10]);
             break;
           case 12 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11]);
             break;
           case 13 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12]);
             break;
           case 14 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13]);
             break;
           case 15 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14]);
             break;
           case 16 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15]);
             break;
           case 17 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16]);
             break;
           case 18 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17]);
             break;
           case 19 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18]);
             break;
           case 20 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19]);
             break;
           case 21 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20]);
             break;
           case 22 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21]);
             break;
           case 23 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22]);
             break;
           case 24 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23]);
             break;
           case 25 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24]);
             break;
           case 26 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25]);
             break;
           case 27 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26]);
             break;
           case 28 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27]);
             break;
           case 29 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28]);
             break;
           case 30 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29]);
             break;
           case 31 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30]);
             break;
           case 32 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31]);
             break;
           case 33 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],
                              Stk[30],Stk[31],Stk[32]);
             break;
           case 34 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33]);
             break;
           case 35 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34]);
             break;
           case 36 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35]);
             break;
           case 37 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36]);
             break;
           case 38 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37]);
             break;
           case 39 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38]);
             break;
           case 40 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39]);
             break;
           case 41 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40]);
             break;
           case 42 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40],Stk[41]);
             break;
           case 43 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40],Stk[41],Stk[42]);
             break;
           case 44 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40],Stk[41],Stk[42],
                            Stk[43]);
             break;
           case 45 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40],Stk[41],Stk[42],
                            Stk[43],Stk[44]);
             break;
           case 46 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40],Stk[41],Stk[42],
                            Stk[43],Stk[44],Stk[45]);
             break;
           case 47 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40],Stk[41],Stk[42],
                            Stk[43],Stk[44],Stk[45],Stk[46]);
             break;
           case 48 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40],Stk[41],Stk[42],
                            Stk[43],Stk[44],Stk[45],Stk[46],Stk[47]);
             break;
           case 49 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40],Stk[41],Stk[42],
                            Stk[43],Stk[44],Stk[45],Stk[46],Stk[47],Stk[48]);
             break;
           case 50 :
             res64 = (*Fn0)(Stk[0],Stk[1],Stk[2],Stk[3],Stk[4],Stk[5],Stk[6],
                            Stk[7],Stk[8],Stk[9],Stk[10],Stk[11],Stk[12],
                            Stk[13],Stk[14],Stk[15],Stk[16],Stk[17],Stk[18],
                            Stk[19],Stk[20],Stk[21],Stk[22],Stk[23],Stk[24],
                            Stk[25],Stk[26],Stk[27],Stk[28],Stk[29],Stk[30],
                            Stk[31],Stk[32],Stk[33],Stk[34],Stk[35],Stk[36],
                            Stk[37],Stk[38],Stk[39],Stk[40],Stk[41],Stk[42],
                            Stk[43],Stk[44],Stk[45],Stk[46],Stk[47],Stk[48],
                            Stk[49]);
             break;
           }
         break;

      case 7 :                /* save 32-bit result */
         Val = *(unsigned long *)s1 + (unsigned long)s2;
         s1 += sizeof(unsigned long *);
         *(unsigned long *)Val = res64 & 0xFFFFFFFF;
         break;

      case 8 :                /* save 64-bit result */
         Val = *(unsigned long *)s1 + (unsigned long)s2;
         s1 += sizeof(unsigned long *);
         *(int64 *)Val = res64;
         break;

      case 9 :                /* copy from addr in eax to offset */
         break;

      case 10 :               /* save errno - call GetLastError() */
         Val = *(unsigned long *)s1 + (unsigned long)s2;
         s1 += sizeof(unsigned long *);
         *(unsigned long *)Val = errno;
         break;

      default :
        return;
    }
  }
}

/* ====================================================================== */

void op_ccall()
{
 /* Stack:

     |=============================|=============================|
     |            BEFORE           |           AFTER             |
     |=============================|=============================|
 top |  str2                       | Result                      |
     |-----------------------------|-----------------------------|
     |  str1 - Pcode to execute    |                             |
     |=============================|=============================|
 */

#define MAX_LOCAL_STRING_LEN 1000

 /* String 1 - Pcode */
 DESCRIPTOR * arg1;
 unsigned char * s1;
 int len1 = 0;
 char ls1[MAX_LOCAL_STRING_LEN+1];

 /* String 2 */
 DESCRIPTOR * arg2;
 unsigned char * s2;
 int len2 = 0;
 char ls2[MAX_LOCAL_STRING_LEN+1];

 arg1 = e_stack - 2;
 k_get_string(arg1);
 if (arg1->data.str.saddr == NULL) k_error("CCALL string 1 null");
 len1 = arg1->data.str.saddr->string_len;
 if (len1 > MAX_LOCAL_STRING_LEN)
  {
   s1 = k_alloc(86, len1+1);
   if (s1 == NULL) k_error("CCALL string 1 memory allocation error");
  }
 else s1 = ls1;
 k_get_c_string(arg1, s1, len1);
   
 arg2 = e_stack - 1;
 k_get_string(arg2);
 if (arg2->data.str.saddr == NULL) k_error("CCALL string 2 null");
 len2 = arg2->data.str.saddr->string_len;
 if (len2 > MAX_LOCAL_STRING_LEN)
  {
   s2 = k_alloc(87, len1+1);
   if (s2 == NULL)
    {
     if (len1 > MAX_LOCAL_STRING_LEN) k_free(s1);
     k_error("CCALL string 2 memory allocation error");
    }
  }
 else s2 = ls2;
 k_get_c_string(arg2, s2, len2);

 k_dismiss();
 k_dismiss();

 ccall_c(s2, s1);

 k_put_string(s1, len1, e_stack++);

 if (len1 > MAX_LOCAL_STRING_LEN) k_free(s1);
 if (len2 > MAX_LOCAL_STRING_LEN) k_free(s2);
}

/* END-CODE */
